/***************************************************************************** * Copyright (C) 2008 EnterpriseDB Corporation. * Copyright (C) 2011 Stado Global Development Group. * * This file is part of Stado. * * Stado is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Stado is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Stado. If not, see <http://www.gnu.org/licenses/>. * * You can find Stado at http://www.stado.us * ****************************************************************************/ /* * ExpressionType.java * */ package org.postgresql.stado.parser; import java.io.Serializable; import java.util.HashMap; import org.postgresql.stado.common.util.ParseCmdLine; import org.postgresql.stado.exception.ErrorMessageRepository; import org.postgresql.stado.exception.InvalidExpressionException; import org.postgresql.stado.exception.XDBServerException; import org.postgresql.stado.metadata.SysColumn; import org.postgresql.stado.parser.handler.TypeConstants; /** * Expression Type is an information class which holds the information about the * type of a particular SQLExpression. * */ public class ExpressionType implements Serializable { /** * */ private static final long serialVersionUID = -8936880257943037513L; public static final int VARCHAR_MAX = 8000; public static final int VARCHAR_UNICODE_MAX = 4000; public static final int VERSION = 2000; public static final int INTLEN = 22; public static final int BIGINTLEN = 40; public static final int DATELEN = 8; public static final int TIMELEN = 8; public static final int TIMESTAMPLEN = 26; public static final int MONTHORDAYNAME = 20; public static final int MAXCHARLEN = 255; public boolean isWithTimeZone; public int type; public int length = -1; public int scale = -1; public int precision = -1; // Type definitions for thoes not supported by java public static final int BLOB_TYPE = java.sql.Types.BLOB; public static final int BOOLEAN_TYPE = java.sql.Types.BOOLEAN; public static final int CLOB_TYPE = java.sql.Types.CLOB; public static final int DOUBLEPRECISION_TYPE = java.sql.Types.DOUBLE; // // public static final int NCHAR_TYPE =115 ; // public static final int NVCHAR_TYPE =116 ; // public static final int NCHARLOB_TYPE =117 ; // public static final int SERIAL_TYPE =118 ; public static final int MACADDR_TYPE = 119; public static final int CIDR_TYPE = 120; public static final int INET_TYPE = 121; public static final int INTERVAL_TYPE = 122; public static final int GEOMETRY_TYPE = 123; public static final int BOX2D_TYPE = 124; public static final int BOX3D_TYPE = 125; public static final int BOX3DEXTENT_TYPE = 126; public static final int REGCLASS_TYPE = 127; // Supported by Java public static final int BIT_TYPE = java.sql.Types.BIT; public static final int BINARY_TYPE = java.sql.Types.BINARY; public static final int VARBINARY_TYPE = java.sql.Types.VARBINARY; public static final int CHAR_TYPE = java.sql.Types.CHAR; public static final int VARCHAR_TYPE = java.sql.Types.VARCHAR; public static final int SMALLINT_TYPE = java.sql.Types.SMALLINT; public static final int INT_TYPE = java.sql.Types.INTEGER; public static final int BIGINT_TYPE = java.sql.Types.BIGINT; public static final int NUMERIC_TYPE = java.sql.Types.NUMERIC; public static final int REAL_TYPE = java.sql.Types.REAL; public static final int FLOAT_TYPE = java.sql.Types.FLOAT; public static final int DATE_TYPE = java.sql.Types.DATE; public static final int TIME_TYPE = java.sql.Types.TIME; public static final int DECIMAL_TYPE = java.sql.Types.DECIMAL; public static final int TIMESTAMP_TYPE = java.sql.Types.TIMESTAMP; public static final int NULL_TYPE = java.sql.Types.NULL; public static final int LEN_SERIAL = 10; /* * Creates a new instance of Expression Type */ public ExpressionType() { } public ExpressionType(int javaType) { type = javaType; } public ExpressionType(int javaType, int length, int precision, int scale) { type = javaType; this.length = length; this.precision = precision; this.scale = scale; } public ExpressionType(SysColumn column) { type = column.getColType(); length = column.getColLength(); precision = column.getColPrecision(); scale = column.getColScale(); } // ------------------------------------------------------------------- /** * Determines whether or not the value passed in is numeric. * * @param java.sql.types code value * * @return <code> true</code> returns true if the expression Type is * numeric * @throws IllegalArgumentException : * Throws an illegalArgumentException if the type is not a valid * type. */ public static boolean isNumeric(int typeCode) { switch (typeCode) { case BLOB_TYPE: return false; case BOOLEAN_TYPE: return false; case BIT_TYPE: case BINARY_TYPE: return false; case CHAR_TYPE: return false; case VARCHAR_TYPE: return false; case DATE_TYPE: return false; case TIME_TYPE: return false; case TIMESTAMP_TYPE: return false; case CLOB_TYPE: return false; case SMALLINT_TYPE: return true; case INT_TYPE: return true; case NUMERIC_TYPE: return true; case REAL_TYPE: return true; case FLOAT_TYPE: return true; case DECIMAL_TYPE: return true; case LEN_SERIAL: return true; case BIGINT_TYPE: return true; case DOUBLEPRECISION_TYPE: return true; case NULL_TYPE: return true; case ExpressionType.MACADDR_TYPE: return false; case ExpressionType.CIDR_TYPE: return false; case ExpressionType.INET_TYPE: return false; case ExpressionType.INTERVAL_TYPE: return false; case ExpressionType.GEOMETRY_TYPE: return false; case ExpressionType.BOX2D_TYPE: return false; case ExpressionType.BOX3D_TYPE: return false; case ExpressionType.BOX3DEXTENT_TYPE: return false; case ExpressionType.REGCLASS_TYPE: return false; default: throw new XDBServerException( ErrorMessageRepository.INVALID_DATATYPE + "( " + typeCode + " )", 0, ErrorMessageRepository.INVALID_DATATYPE_CODE); } } /** * * @return <code> true</code> returns true if the expression Type is * numeric * @throws IllegalArgumentException : * Throws an illegalArgumentException if the type is not a valid * type. */ public boolean isNumeric() { return isNumeric(this.type); } // ------------------------------------------------------------------- /** * Determines whether or not the value passed in is InExactNumeric * (float, real, double) * * @param java.sql.types code value * * @return <code> true</code> returns true if the expression Type is * InExactNumeric */ public static boolean isInExactNumeric(int typeCode) { if (typeCode == REAL_TYPE || typeCode == FLOAT_TYPE || typeCode == DOUBLEPRECISION_TYPE) { return true; } else { return false; } } /** * * @return <code> true</code> returns true if the expression Type is * InExactNumeric (real, float, double) */ public boolean isInExactNumeric() { return isInExactNumeric(this.type); } /** * * @return <code> true</code> returns true if the expression Type is * bit * @throws IllegalArgumentException : * Throws an illegalArgumentException if the type is not a valid * type. */ public boolean isBit() { switch (this.type) { case BOOLEAN_TYPE: case BIT_TYPE: case BINARY_TYPE: case NULL_TYPE: return true; default: return false; } } /** * * @return <code> true</code> returns true if the expression Type is * varchar * @throws IllegalArgumentException : * Throws an illegalArgumentException if the type is not a valid * type. */ public boolean isCharacter() { switch (this.type) { case VARCHAR_TYPE: return true; default: return false; } } // ----------------------------------------------------------------------- /** * * @return A string which is the String representaion of this particular * expression * @throws IllegalArgumentException : * An exception is thrown when the Type is set to a unknown data * type */ public String getTypeString() { String typeString = ""; HashMap<String, String> params = new HashMap<String, String>(); params.put("length", new String(length + "")); params.put("scale", new String(scale + "")); params.put("precision", new String(precision + "")); switch (type) { case java.sql.Types.BIT: if (length > 1) { typeString = TypeConstants.BIT_TEMPLATE; } else { typeString = "BIT"; } typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.BINARY: if (length > 1) { typeString = TypeConstants.BIT_TEMPLATE; } else { typeString = "BIT"; } typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.VARBINARY: typeString = "VARBIT"; break; case java.sql.Types.CHAR: typeString = TypeConstants.CHAR_TEMPLATE; typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.VARCHAR: typeString = TypeConstants.VARCHAR_TEMPLATE; typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.SMALLINT: typeString = TypeConstants.SMALLINT_TEMPLATE; typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.INTEGER: typeString = TypeConstants.INTEGER_TEMPLATE; typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.BIGINT: typeString = TypeConstants.BIGINTEGER_TEMPLATE; typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.DECIMAL: case java.sql.Types.NUMERIC: if (precision == -1) { typeString = TypeConstants.NUMERIC_TEMPLATE_WITHOUT_PRECISION; } else if (scale == -1) { typeString = TypeConstants.NUMERIC_TEMPLATE_WITHOUT_SCALE; } else { typeString = TypeConstants.NUMERIC_TEMPLATE; } typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.REAL: typeString = TypeConstants.REAL_TEMPLATE; break; case java.sql.Types.FLOAT: if (length > 0) { typeString = TypeConstants.FLOAT_TEMPLATE; typeString = ParseCmdLine.substitute(typeString, params); } else { typeString = TypeConstants.REAL_TEMPLATE; } break; case java.sql.Types.DATE: typeString = TypeConstants.DATE_TEMPLATE; typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.TIME: typeString = TypeConstants.TIME_TEMPLATE; typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.TIMESTAMP: typeString = TypeConstants.TIMESTAMP_TEMPLATE; typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.DOUBLE: typeString = TypeConstants.DOUBLE_TEMPLATE; typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.BOOLEAN: typeString = TypeConstants.BOOLEAN_TEMPLATE; typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.CLOB: typeString = TypeConstants.TEXT_TEMPLATE; typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.BLOB: typeString = TypeConstants.BLOB_TEMPLATE; typeString = ParseCmdLine.substitute(typeString, params); break; case java.sql.Types.NULL: // for null type we dont return any string break; case ExpressionType.MACADDR_TYPE: typeString = "MACADDR "; break; case ExpressionType.CIDR_TYPE: typeString = "CIDR "; break; case ExpressionType.INET_TYPE: typeString = "INET "; break; case ExpressionType.GEOMETRY_TYPE: typeString = "GEOMETRY "; break; case ExpressionType.BOX2D_TYPE: typeString = "BOX2D "; break; case ExpressionType.BOX3D_TYPE: typeString = "BOX3D "; break; case ExpressionType.BOX3DEXTENT_TYPE: typeString = "BOX3D_EXTENT "; break; case ExpressionType.REGCLASS_TYPE: typeString = "REGCLASS "; break; case ExpressionType.INTERVAL_TYPE: typeString = "INTERVAL "; break; default: throw new XDBServerException( ErrorMessageRepository.INVALID_DATATYPE + "( " + type + " )", 0, ErrorMessageRepository.INVALID_DATATYPE_CODE); } return typeString; } /** * */ public String getLengthString() { if (length > 0) { return "( " + length + " )"; } else { return ""; } } // ------------------------------------------------------------------- /*************************************************************************** * The function allows setting of all the variables that completely define * an expression. Pre Condition: None * * @param type * This defines the data type of the expression, and the value is * same as that of java.sql.Types * @param length * This defines the length of the data * @param precision * The total length of the datatype - only makes sense if the * datatype is numeric, decimal. * @param scale * */ public void setExpressionType(int type, int length, int precision, int scale) { this.type = type; this.length = length; this.precision = precision; this.scale = scale; } /*************************************************************************** * PreCondition: The expressions should be compatible with each other, * incase it is not a illegal argument exception is thrown. * * * @param aExprTypeHelper * A helper class which has 3 fields. ( 2 Exprtype , 1 Operator ) * Allows easy ineraction between functions * @return Just returns the expression type after checking the semantics of * the expression.eg. if boolean and clob columns exist in the same * expression then it will not accept it. * * The Function determines the new expression that will be returned when two * expressions are joined with the specified operator. */ public ExpressionType GetExpressionType(ExprTypeHelper aExprTypeHelper) { ExpressionType exprType = checkSemanticsAndReturnOutputType(aExprTypeHelper); return exprType; } /*************************************************************************** * * @param aExprTypeHelper * @return A expression type , after combining the different data types * * The function not only checks if these two expressions can be joined by * the given operator but also return the appropriate output expression * type. */ private ExpressionType checkSemanticsAndReturnOutputType( ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = null; int leftType = aExprTypeHelper.leftExprType.type; int rightType = aExprTypeHelper.righExprType.type; exprTypeToReturn = HandleOperator(aExprTypeHelper.Operator); if (exprTypeToReturn != null) { return exprTypeToReturn; } // Determine if any of the expressions is a BIT TYPE if (leftType == ExpressionType.INTERVAL_TYPE || rightType == ExpressionType.INTERVAL_TYPE) { exprTypeToReturn = HandleInterval(aExprTypeHelper); return exprTypeToReturn; } if (leftType == ExpressionType.CIDR_TYPE || rightType == ExpressionType.CIDR_TYPE) { exprTypeToReturn = HandleCidr(aExprTypeHelper); return exprTypeToReturn; } if (leftType == ExpressionType.INET_TYPE || rightType == ExpressionType.INET_TYPE) { exprTypeToReturn = HandleInet(aExprTypeHelper); return exprTypeToReturn; } if (leftType == ExpressionType.GEOMETRY_TYPE || rightType == ExpressionType.GEOMETRY_TYPE) { exprTypeToReturn = HandleGeometry(aExprTypeHelper); return exprTypeToReturn; } if (leftType == ExpressionType.BOX2D_TYPE || rightType == ExpressionType.BOX2D_TYPE) { exprTypeToReturn = HandleBox2D(aExprTypeHelper); return exprTypeToReturn; } if (leftType == ExpressionType.BOX3D_TYPE || rightType == ExpressionType.BOX3D_TYPE) { exprTypeToReturn = HandleBox3D(aExprTypeHelper); return exprTypeToReturn; } if (leftType == ExpressionType.BOX3DEXTENT_TYPE || rightType == ExpressionType.BOX3DEXTENT_TYPE) { exprTypeToReturn = HandleBox3DExtent(aExprTypeHelper); return exprTypeToReturn; } if (leftType == ExpressionType.TIME_TYPE || rightType == ExpressionType.TIME_TYPE) { exprTypeToReturn = HandleTimeType(aExprTypeHelper); } if (leftType == ExpressionType.CLOB_TYPE || rightType == ExpressionType.CLOB_TYPE) { exprTypeToReturn = HandleClobType(aExprTypeHelper); } else if (leftType == ExpressionType.BLOB_TYPE || rightType == ExpressionType.BLOB_TYPE) { exprTypeToReturn = HandleBlobType(aExprTypeHelper); } else if (leftType == ExpressionType.BINARY_TYPE || rightType == ExpressionType.BINARY_TYPE) { exprTypeToReturn = HandleBinaryType(aExprTypeHelper); } else if (leftType == ExpressionType.BIT_TYPE || rightType == ExpressionType.BIT_TYPE) { // Allow the bit type Handler to take care of it -- TODO // Specifications // for BIT type handling are not availabe . exprTypeToReturn = HandleBitType(aExprTypeHelper); } // The boolean type is handled the same way as BIT TYPE else if (leftType == ExpressionType.BOOLEAN_TYPE || rightType == ExpressionType.BOOLEAN_TYPE) { // exprTypeToReturn = HandleBooleanType(aExprTypeHelper); } else if (leftType == ExpressionType.DOUBLEPRECISION_TYPE || rightType == ExpressionType.DOUBLEPRECISION_TYPE) { exprTypeToReturn = HandleDoublePrecison(aExprTypeHelper); } else if (leftType == ExpressionType.CHAR_TYPE || rightType == ExpressionType.CHAR_TYPE) { exprTypeToReturn = HandleCharType(aExprTypeHelper); } else if (leftType == ExpressionType.VARCHAR_TYPE || rightType == ExpressionType.VARCHAR_TYPE) { exprTypeToReturn = HandleVarCharType(aExprTypeHelper); } else if (leftType == ExpressionType.SMALLINT_TYPE || rightType == ExpressionType.SMALLINT_TYPE) { exprTypeToReturn = HandleSmallInt(aExprTypeHelper); } else if (leftType == ExpressionType.INT_TYPE || rightType == ExpressionType.INT_TYPE) { exprTypeToReturn = HandleInt(aExprTypeHelper); } else if (leftType == ExpressionType.BIGINT_TYPE || rightType == ExpressionType.BIGINT_TYPE) { exprTypeToReturn = HandleBigInt(aExprTypeHelper); } else if (leftType == ExpressionType.NUMERIC_TYPE || rightType == ExpressionType.NUMERIC_TYPE) { exprTypeToReturn = HandleNumeric(aExprTypeHelper); } else if (leftType == ExpressionType.REAL_TYPE || rightType == ExpressionType.REAL_TYPE) { exprTypeToReturn = HandleReal(aExprTypeHelper); } else if (leftType == ExpressionType.FLOAT_TYPE || rightType == ExpressionType.FLOAT_TYPE) { exprTypeToReturn = HandleFloat(aExprTypeHelper); } else if (leftType == ExpressionType.DATE_TYPE || rightType == ExpressionType.DATE_TYPE) { exprTypeToReturn = HandleDate(aExprTypeHelper); } else if (leftType == ExpressionType.DECIMAL_TYPE || rightType == ExpressionType.DECIMAL_TYPE) { exprTypeToReturn = HandleDecimal(aExprTypeHelper); } else if (leftType == ExpressionType.TIMESTAMP_TYPE || rightType == ExpressionType.TIMESTAMP_TYPE) { exprTypeToReturn = HandleTimeStamp(aExprTypeHelper); } if (exprTypeToReturn == null) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); } else { return exprTypeToReturn; } } /* At present we don't have any specification for it -- */ /** * This function takes care of combining BIT type with other datatypes and * returns a vaild expression type. * * @param aExprTypeHelper - * This is a helper object which contains 3 items 2 expression * and 1 Operator. * @return The expression type which will be a result after combining these * two expression */ private ExpressionType HandleBitType(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = null; int leftType = aExprTypeHelper.leftExprType.type; int rightType = aExprTypeHelper.righExprType.type; if (leftType == ExpressionType.BOOLEAN_TYPE || rightType == ExpressionType.BOOLEAN_TYPE) { } else if (leftType == ExpressionType.BLOB_TYPE || rightType == ExpressionType.BLOB_TYPE) { } else if (leftType == ExpressionType.BOOLEAN_TYPE || rightType == ExpressionType.BOOLEAN_TYPE) { } else if (leftType == ExpressionType.CLOB_TYPE || rightType == ExpressionType.CLOB_TYPE) { } else if (leftType == ExpressionType.DOUBLEPRECISION_TYPE || rightType == ExpressionType.DOUBLEPRECISION_TYPE) { } else if (leftType == ExpressionType.CHAR_TYPE || rightType == ExpressionType.CHAR_TYPE) { } else if (leftType == ExpressionType.VARCHAR_TYPE || rightType == ExpressionType.VARCHAR_TYPE) { } else if (leftType == ExpressionType.SMALLINT_TYPE || rightType == ExpressionType.SMALLINT_TYPE) { } else if (leftType == ExpressionType.INT_TYPE || rightType == ExpressionType.INT_TYPE) { } else if (leftType == ExpressionType.NUMERIC_TYPE || rightType == ExpressionType.NUMERIC_TYPE) { } else if (leftType == ExpressionType.REAL_TYPE || rightType == ExpressionType.REAL_TYPE) { } else if (leftType == ExpressionType.FLOAT_TYPE || rightType == ExpressionType.FLOAT_TYPE) { } else if (leftType == ExpressionType.DATE_TYPE || rightType == ExpressionType.DATE_TYPE) { } else if (leftType == ExpressionType.DECIMAL_TYPE || rightType == ExpressionType.DECIMAL_TYPE) { } else if (leftType == ExpressionType.TIMESTAMP_TYPE || rightType == ExpressionType.TIMESTAMP_TYPE) { } return exprTypeToReturn; } /* At present we don't have any specification for it -- */ /** * This function takes care of combining BIT type with other datatypes and * returns a vaild expression type. * * @param aExprTypeHelper - * This is a helper object which contains 3 items 2 expression * and 1 Operator. * @return The expression type which will be a result after combining these * two expression */ private ExpressionType HandleBinaryType(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = null; int otherType; if (aExprTypeHelper.leftExprType.type == ExpressionType.BINARY_TYPE) { otherType = aExprTypeHelper.righExprType.type; } else { otherType = aExprTypeHelper.leftExprType.type; } if (otherType == ExpressionType.BINARY_TYPE || otherType == ExpressionType.CHAR_TYPE || otherType == ExpressionType.VARCHAR_TYPE) { int leftLen = aExprTypeHelper.leftExprType.length; int rightLen = aExprTypeHelper.righExprType.length; // Rely on backend check if length can not be determined if (leftLen == -1 || rightLen == -1) { leftLen = -1; rightLen = -1; } if (leftLen == rightLen) { exprTypeToReturn = new ExpressionType(); exprTypeToReturn.setExpressionType(ExpressionType.BINARY_TYPE, leftLen, 0, 0); } } return exprTypeToReturn; } // -- Handling Blob Type Start /** * This function takes care of combining BLOB type with other datatypes and * returns a vaild expression type - Since we cannot have any expressions * with blobs we throw a IllegalArgumentException. * * @param aExprTypeHelper - * This is a helper object which contains 3 items 2 expression * and 1 Operator. * @return The expression type which will be a result after combining these * two expression */ private ExpressionType HandleBlobType(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; int rightType = aExprTypeHelper.righExprType.type; if (leftType == ExpressionType.BLOB_TYPE || rightType == ExpressionType.BLOB_TYPE || leftType == ExpressionType.NULL_TYPE || rightType == ExpressionType.NULL_TYPE) { exprTypeToReturn.setExpressionType(ExpressionType.BLOB_TYPE, -1, -1, -1); } else if (leftType == ExpressionType.BOOLEAN_TYPE || rightType == ExpressionType.BOOLEAN_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Boolean variable and a Blob // cannot be used with binary operator :" + Operator); } else if (leftType == ExpressionType.CLOB_TYPE || rightType == ExpressionType.CLOB_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException(" variable and a Blob cannot be // used with binary operator :" + Operator); } else if (leftType == ExpressionType.DOUBLEPRECISION_TYPE || rightType == ExpressionType.DOUBLEPRECISION_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // hrow new XDBSemanticException("Double and a Blob cannot be used // with binary operator :" + Operator); } else if (leftType == ExpressionType.CHAR_TYPE || rightType == ExpressionType.CHAR_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Char and a Blob cannot be used // with binary operator :" + Operator); } else if (leftType == ExpressionType.VARCHAR_TYPE || rightType == ExpressionType.VARCHAR_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Var Char and a Blob cannot be // used with binary operator :" + Operator); } else if (leftType == ExpressionType.SMALLINT_TYPE || rightType == ExpressionType.SMALLINT_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Small Int and a Blob cannot be // used with binary operator :" + Operator); } else if (leftType == ExpressionType.INT_TYPE || rightType == ExpressionType.INT_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); } else if (leftType == ExpressionType.BIGINT_TYPE || rightType == ExpressionType.BIGINT_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("INT and a Blob cannot be used // with binary operator :" + Operator); } else if (leftType == ExpressionType.NUMERIC_TYPE || rightType == ExpressionType.NUMERIC_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("INT and a Blob cannot be used // with binary operator :" + Operator); } else if (leftType == ExpressionType.REAL_TYPE || rightType == ExpressionType.REAL_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("REAL and a Blob cannot be used // with binary operator :" + Operator); } else if (leftType == ExpressionType.FLOAT_TYPE || rightType == ExpressionType.FLOAT_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("FLOAT and a Blob cannot be used // with binary operator :" + Operator); } else if (leftType == ExpressionType.DATE_TYPE || rightType == ExpressionType.DATE_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("DATE and a Blob cannot be used // with binary operator :" + Operator); } else if (leftType == ExpressionType.DECIMAL_TYPE || rightType == ExpressionType.DECIMAL_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("DECIMAL and a Blob cannot be used // with binary operator :" + Operator); } else if (leftType == ExpressionType.TIMESTAMP_TYPE || rightType == ExpressionType.TIMESTAMP_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("TIME STAMP and a Blob cannot be // used with binary operator :" + Operator); } return exprTypeToReturn; } // Handling Bolb type ends // Handling Boolean Typ starts /** * This function takes care of combining BOOLEAN type with other datatypes * and returns a vaild expression type - Please noted that we will not * handle BIT type with boolean here as it is already taken care of in * handleBitType() * * @param aExprTypeHelper - * This is a helper object which contains 3 items 2 expression * and 1 Operator. * @return The expression type which will be a result after combining these * two expression */ private ExpressionType HandleBooleanType(ExprTypeHelper aExprTypeHelper) { // Allocate Memory for the Expression to return ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; // This will be filled with the NON- BOOLEAN expression ExpressionType typeToCheck; // Check to see which one is boolean and assign the non boolean to // "typeToCheck" if (leftType == ExpressionType.BOOLEAN_TYPE) { typeToCheck = aExprTypeHelper.righExprType; } else { typeToCheck = aExprTypeHelper.leftExprType; } // Incase the Other Type is also boolean -- Set the expression type to // boolean // We donot have any consideration for precision,scale or length if (typeToCheck.type == ExpressionType.BOOLEAN_TYPE || typeToCheck.type == ExpressionType.NULL_TYPE) { exprTypeToReturn.setExpressionType(ExpressionType.BOOLEAN_TYPE, -1, -1, -1); } // The CLOB datatype cannot interact with Boolean Data Type - There fore // we just throw // an exception here else if (typeToCheck.type == ExpressionType.CLOB_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("CLOB and Boolean cannot be used // with binary operator :" + Operator); } // Incase we have BLOB else if (typeToCheck.type == ExpressionType.CLOB_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("BLOB and Boolean cannot be used // with binary operator :" + Operator); } // Incase of Double we simply return a double with the length and // precision of a double. // assuming that the boolean variable will be 0 or 1 // Some DBs do not allow interaction between boolean varibles and other // types else if (typeToCheck.type == ExpressionType.DOUBLEPRECISION_TYPE) { exprTypeToReturn.setExpressionType( ExpressionType.DOUBLEPRECISION_TYPE, typeToCheck.length, typeToCheck.precision, typeToCheck.scale); } // For Char type we dont think of any valid expression, there fore like // NVCHAR,VARCHAR,CHARLOB etc. // We throw an exception. else if (typeToCheck.type == ExpressionType.CHAR_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Boolean and Char cannot be used // with binary operator :" + Operator); } // For VarChar -- similar treatment as CHAR etc. else if (typeToCheck.type == ExpressionType.VARCHAR_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Boolean and VarChar cannot be // used with binary operator :" + Operator); } // SMALL INT is a numeric type there fore we will allow the boolean to // take a value of 0 or 1 // The length , precison and scale are all -1.However a small int is of // 6 fields long. // However this might not make much change. else if (typeToCheck.type == ExpressionType.SMALLINT_TYPE || typeToCheck.type == NUMERIC_TYPE | typeToCheck.type == REAL_TYPE || typeToCheck.type == FLOAT_TYPE || typeToCheck.type == DECIMAL_TYPE || typeToCheck.type == INT_TYPE || typeToCheck.type == BIGINT_TYPE) { // Some DBs do not support Boolean // interaction with any other type // but we still leave this here so that it can complain when we go // and hit the database. exprTypeToReturn.setExpressionType(typeToCheck.type, typeToCheck.length, typeToCheck.precision, typeToCheck.scale); } else if (typeToCheck.type == ExpressionType.DATE_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Boolean and Date cannot be used // with binary operator :" + Operator); } // Incase this is a TIMESTAMP no possible interaction else if (typeToCheck.type == ExpressionType.TIMESTAMP_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Boolean and TimeStamp cannot be // used with binary operator :" + Operator); } // Incase this is a TIME else if (typeToCheck.type == ExpressionType.TIME_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Boolean and Time cannot be used // with binary operator :" + Operator); } return exprTypeToReturn; } // Handling Boolean Type Ends private ExpressionType HandleCharType(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; // int rightType = aExprTypeHelper.righExprType.type; String Operator = aExprTypeHelper.Operator; ExpressionType typeToCheck; ExpressionType aCharType = null; if (Operator.equals("||") == false) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Only Supported operation between // a Char and Any other Datatype is concatenation"); } if (leftType == ExpressionType.CHAR_TYPE) { typeToCheck = aExprTypeHelper.righExprType; aCharType = aExprTypeHelper.leftExprType; } else { typeToCheck = aExprTypeHelper.leftExprType; aCharType = aExprTypeHelper.righExprType; } if (typeToCheck.type == ExpressionType.CHAR_TYPE || typeToCheck.type == ExpressionType.NULL_TYPE) { // if both are char type then we should have add the lengths of both // left and right // The precision and scale do not matter in this case exprTypeToReturn.setExpressionType(ExpressionType.CHAR_TYPE, aCharType.length + typeToCheck.length, -1, -1); } else if (typeToCheck.type == ExpressionType.VARCHAR_TYPE) { exprTypeToReturn.setExpressionType(ExpressionType.VARCHAR_TYPE, aCharType.length + typeToCheck.length, -1, -1); } else if (typeToCheck.type == ExpressionType.SMALLINT_TYPE) { // The default size of ConvertSmallIntToCharType(exprTypeToReturn, aCharType); } else if (typeToCheck.type == INT_TYPE) { // The default size of ConvertIntToCharType(exprTypeToReturn, aCharType); } else if (typeToCheck.type == BIGINT_TYPE) { // The default size of ConvertBigIntToCharType(exprTypeToReturn, aCharType); } else if (typeToCheck.type == ExpressionType.REAL_TYPE || typeToCheck.type == ExpressionType.FLOAT_TYPE) { ConvertRealToChar(typeToCheck, exprTypeToReturn, aCharType); } else if (typeToCheck.type == ExpressionType.DATE_TYPE) { // The date lenght is less than 3o for sure - I am not sure how // long it can be. exprTypeToReturn.setExpressionType(ExpressionType.CHAR_TYPE, aCharType.length + 30, -1, -1); } else if (typeToCheck.type == ExpressionType.DECIMAL_TYPE || typeToCheck.type == ExpressionType.NUMERIC_TYPE) { ConvertNumTypeCharType(typeToCheck, exprTypeToReturn, aCharType); } else if (typeToCheck.type == ExpressionType.TIMESTAMP_TYPE) { // The Lenght of the time stamp varies in DBs, but to be on the // safer side we are putting it at 30 exprTypeToReturn.setExpressionType(ExpressionType.CHAR_TYPE, aCharType.length + 30, -1, -1); } return exprTypeToReturn; } /* * This function converts a Real to Char - The real can be specifed as Real , * or Real(10) . where 10 is the length. * * Therefore in case we just have real - we * allow a length of 16 incase it is user specified, that is used. * * This same thing is valid for VARCHAR,NCHAR,NVCHAR, and CHAR */ /** * This is a helper function which changes the expression type to the right * value basically it sets the lenght to 16 + the lenght already specified. * * @param typeToCheck * @param exprTypeToReturn * @param aCharType */ private void ConvertRealToChar(ExpressionType typeToCheck, ExpressionType exprTypeToReturn, ExpressionType aCharType) { // The length of a real is 16. Incase the user has specified the lenght // we can use that length if (typeToCheck.length <= 0) { exprTypeToReturn.setExpressionType(aCharType.type, aCharType.length + 16, -1, -1); } else { exprTypeToReturn.setExpressionType(aCharType.type, aCharType.length + typeToCheck.length, -1, -1); } } /* * This function converts a Numeric Type to a character Type -- according to * some DBs, a Numeric or decimal type with out any specification is mapped * to FIXED(5) When ever there is specification , the specs is used to * create the column. * * Therefore we have used char.length + 5 in the default case * * and * * char.length + typeToCheck.length in the case when the precision and scale * are specified. * */ /** * * @param typeToCheck * @param exprTypeToReturn * @param aCharType */ private void ConvertNumTypeCharType(ExpressionType typeToCheck, ExpressionType exprTypeToReturn, ExpressionType aCharType) { // Incase the user does not specify any value for // decimal -- some DBs use length 5 as default if (typeToCheck.length <= 0) { exprTypeToReturn.setExpressionType(aCharType.type, aCharType.length + 5, -1, -1); } else { exprTypeToReturn.setExpressionType(aCharType.type, aCharType.length + typeToCheck.length, -1, -1); } } // Handle Char ends // Handle Var Char Starts /** * This funtion handles VarChar Combining with other datatypes * * @param aExprTypeHelper * @return */ private ExpressionType HandleVarCharType(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; // int rightType = aExprTypeHelper.righExprType.type; String Operator = aExprTypeHelper.Operator; ExpressionType typeToCheck = null; ExpressionType aVarCharType = null; // Check if we are comparing strings if (Operator.equals(">") || Operator.equals(">=") || Operator.equals("<") || Operator.equals("<=") || Operator.equals("!=") || Operator.equals("<>") || Operator.equals("=") || Operator.equals("is") || Operator.equals("is not") || Operator.equals("~") || Operator.equals("!~") || Operator.equals("~*") || Operator.equals("!~*")) { // return BOOLEAN exprTypeToReturn.setExpressionType(ExpressionType.BOOLEAN_TYPE, -1, -1, -1); return exprTypeToReturn; } if (leftType == ExpressionType.CHAR_TYPE) { typeToCheck = aExprTypeHelper.righExprType; aVarCharType = aExprTypeHelper.leftExprType; } else { typeToCheck = aExprTypeHelper.leftExprType; aVarCharType = aExprTypeHelper.righExprType; } if (Operator.equals("||") == false) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Only Supported operation between // a Char and Any other Datatype is concatenation"); } if (typeToCheck.type == ExpressionType.VARCHAR_TYPE || typeToCheck.type == ExpressionType.NULL_TYPE) { // If both are var char type we can add the lengths for both these // variables exprTypeToReturn.setExpressionType(ExpressionType.VARCHAR_TYPE, aVarCharType.length + typeToCheck.length, -1, -1); } else if (typeToCheck.type == ExpressionType.SMALLINT_TYPE) { // The default size of ConvertSmallIntToCharType(exprTypeToReturn, aVarCharType); } else if (typeToCheck.type == INT_TYPE) { // The default size of ConvertIntToCharType(exprTypeToReturn, aVarCharType); } else if (typeToCheck.type == BIGINT_TYPE) { // The default size of ConvertBigIntToCharType(exprTypeToReturn, aVarCharType); } else if (typeToCheck.type == ExpressionType.NUMERIC_TYPE || typeToCheck.type == ExpressionType.DECIMAL_TYPE) { ConvertNumTypeCharType(typeToCheck, exprTypeToReturn, aVarCharType); } else if (typeToCheck.type == ExpressionType.REAL_TYPE || typeToCheck.type == FLOAT_TYPE) { // Converting real type to Var Char type ConvertRealToChar(typeToCheck, exprTypeToReturn, aVarCharType); } else if (typeToCheck.type == ExpressionType.DATE_TYPE) { exprTypeToReturn.setExpressionType(ExpressionType.VARCHAR_TYPE, aVarCharType.length + 30, -1, -1); } else if (typeToCheck.type == ExpressionType.TIMESTAMP_TYPE) { exprTypeToReturn.setExpressionType(ExpressionType.VARCHAR_TYPE, aVarCharType.length + 30, -1, -1); } return exprTypeToReturn; } /* * This function converts a Small int or Int type to char type , where char * type can be -- NVCHAR,CHAR,VCHAR and NCHAR. * * Even Though - smallint is 6 units in size we use 10 , which should not * make much difference. Use 10 units in length */ /** * * @param exprTypeToReturn * @param aCharType */ public void ConvertSmallIntToCharType(ExpressionType exprTypeToReturn, ExpressionType aCharType) { exprTypeToReturn.setExpressionType(aCharType.type, aCharType.length + 10, -1, -1); } /** * * @param exprTypeToReturn * @param aCharType */ public void ConvertIntToCharType(ExpressionType exprTypeToReturn, ExpressionType aCharType) { exprTypeToReturn.setExpressionType(aCharType.type, aCharType.length + 11, -1, -1); } /** * * @param exprTypeToReturn * @param aCharType */ public void ConvertBigIntToCharType(ExpressionType exprTypeToReturn, ExpressionType aCharType) { exprTypeToReturn.setExpressionType(aCharType.type, aCharType.length + 17, -1, -1); } // Handle Var Char Ends // Handle TimeStamp /** * * @param aExprTypeHelper * @return ExpressionType - The expression Type is a valid expression type * which is a result of combining the two expressions */ private ExpressionType HandleTimeStamp(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; int rightType = aExprTypeHelper.righExprType.type; if (leftType == ExpressionType.TIMESTAMP_TYPE && rightType == ExpressionType.TIMESTAMP_TYPE && aExprTypeHelper.Operator.equals("-")) { exprTypeToReturn.setExpressionType(ExpressionType.INTERVAL_TYPE, -1, -1, -1); return exprTypeToReturn; } if (leftType == ExpressionType.TIMESTAMP_TYPE || rightType == ExpressionType.TIMESTAMP_TYPE || leftType == ExpressionType.NULL_TYPE || rightType == ExpressionType.NULL_TYPE) { exprTypeToReturn.setExpressionType(ExpressionType.TIMESTAMP_TYPE, ExpressionType.TIMESTAMPLEN, -1, -1); } return exprTypeToReturn; } private ExpressionType HandleInterval(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); exprTypeToReturn.setExpressionType(ExpressionType.INTERVAL_TYPE, -1, -1, -1); return exprTypeToReturn; } // Return INET type if any of the expression types is INET private ExpressionType HandleInet(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); String Operator = aExprTypeHelper.Operator; if (Operator.equals("&") == true || Operator.equals("|") == true || Operator.equals("+") == true || Operator.equals("-") == true) { exprTypeToReturn.setExpressionType(ExpressionType.INET_TYPE, -1, -1, -1); return exprTypeToReturn; } // return BOOLEAN for other operators exprTypeToReturn.setExpressionType(ExpressionType.BOOLEAN_TYPE, -1, -1, -1); return exprTypeToReturn; } // Return CIDR type if any of the expression types is CIDR private ExpressionType HandleCidr(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); String Operator = aExprTypeHelper.Operator; if (Operator.equals("&") == true || Operator.equals("|") == true || Operator.equals("+") == true || Operator.equals("-") == true) { exprTypeToReturn.setExpressionType(ExpressionType.CIDR_TYPE, -1, -1, -1); return exprTypeToReturn; } // return BOOLEAN for other operators exprTypeToReturn.setExpressionType(ExpressionType.BOOLEAN_TYPE, -1, -1, -1); return exprTypeToReturn; } // Return BOOLEAN type if any of the expression types is GEOMETRY private ExpressionType HandleGeometry(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); // return BOOLEAN for other operators exprTypeToReturn.setExpressionType(ExpressionType.BOOLEAN_TYPE, -1, -1, -1); return exprTypeToReturn; } // Return BOOLEAN type if any of the expression types is BOX2D private ExpressionType HandleBox2D(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); // return BOOLEAN for other operators exprTypeToReturn.setExpressionType(ExpressionType.BOOLEAN_TYPE, -1, -1, -1); return exprTypeToReturn; } // Return BOOLEAN type if any of the expression types is BOX3D private ExpressionType HandleBox3D(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); // return BOOLEAN for other operators exprTypeToReturn.setExpressionType(ExpressionType.BOOLEAN_TYPE, -1, -1, -1); return exprTypeToReturn; } // Return BOOLEAN type if any of the expression types is BOX3DEXTENT private ExpressionType HandleBox3DExtent(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); // return BOOLEAN for other operators exprTypeToReturn.setExpressionType(ExpressionType.BOOLEAN_TYPE, -1, -1, -1); return exprTypeToReturn; } // Handle Time Stamp // Handle Decimal /** * * @param aExprTypeHelper * @return ExpressionType - The expression Type is a valid expression type * which is a result of combining the two expressions */ private ExpressionType HandleDecimal(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; int rightType = aExprTypeHelper.righExprType.type; String Operator = aExprTypeHelper.Operator; ExpressionType typeToCheck = null; ExpressionType aDecType = null; if (Operator.equals("||") == true) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Concatenation is not supported // between decimals"); } if (leftType == ExpressionType.CHAR_TYPE) { typeToCheck = aExprTypeHelper.righExprType; aDecType = aExprTypeHelper.leftExprType; } else { typeToCheck = aExprTypeHelper.leftExprType; aDecType = aExprTypeHelper.righExprType; } if (typeToCheck.type == ExpressionType.DECIMAL_TYPE || typeToCheck.type == ExpressionType.NULL_TYPE) { exprTypeToReturn = MergeNumericTypes(typeToCheck, aDecType); } else if (leftType == ExpressionType.TIMESTAMP_TYPE || rightType == ExpressionType.TIMESTAMP_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Operation Not Compatibke"); } return exprTypeToReturn; } // Handle Decimal end // Handle Date Starts /** * * @param aExprTypeHelper * @return ExpressionType - The expression Type is a valid expression type * which is a result of combining the two expressions */ private ExpressionType HandleDate(ExprTypeHelper aExprTypeHelper) { // We // should // never // come // here ExpressionType exprTypeToReturn; int leftType = aExprTypeHelper.leftExprType.type; int rightType = aExprTypeHelper.righExprType.type; int typeToCheck = -1; if (leftType == ExpressionType.DATE_TYPE) { typeToCheck = rightType; } else { typeToCheck = leftType; } if (typeToCheck == ExpressionType.NULL_TYPE) { exprTypeToReturn = new ExpressionType(); exprTypeToReturn.type = ExpressionType.DATE_TYPE; exprTypeToReturn.precision = -1; exprTypeToReturn.length = ExpressionType.DATELEN; exprTypeToReturn.scale = -1; return exprTypeToReturn; } if (typeToCheck == ExpressionType.INTERVAL_TYPE) { exprTypeToReturn = new ExpressionType(); exprTypeToReturn.type = ExpressionType.TIMESTAMP_TYPE; exprTypeToReturn.precision = -1; exprTypeToReturn.length = ExpressionType.DATELEN; exprTypeToReturn.scale = -1; return exprTypeToReturn; } if (typeToCheck == ExpressionType.TIME_TYPE) { exprTypeToReturn = new ExpressionType(); exprTypeToReturn.type = ExpressionType.TIME_TYPE; exprTypeToReturn.precision = -1; exprTypeToReturn.length = ExpressionType.TIMELEN; exprTypeToReturn.scale = -1; return exprTypeToReturn; } if (typeToCheck == ExpressionType.DATE_TYPE) { exprTypeToReturn = new ExpressionType(); exprTypeToReturn.type = ExpressionType.DATE_TYPE; exprTypeToReturn.precision = -1; exprTypeToReturn.length = ExpressionType.DATELEN; exprTypeToReturn.scale = -1; return exprTypeToReturn; } if (typeToCheck == ExpressionType.TIMESTAMP_TYPE) { exprTypeToReturn = new ExpressionType(); exprTypeToReturn.type = ExpressionType.VARCHAR_TYPE; exprTypeToReturn.length = ExpressionType.VARCHAR_MAX; exprTypeToReturn.precision = -1; exprTypeToReturn.scale = -1; return exprTypeToReturn; } else { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); } // throw new XDBSemanticException("The Operation is invalid"); } // Handle Date Ends // Handle Float /** * * @param aExprTypeHelper * @return ExpressionType - The expression Type is a valid expression type * which is a result of combining the two expressions */ private ExpressionType HandleFloat(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; ExpressionType typeToCheck = null; ExpressionType aFloatType = null; if (leftType == ExpressionType.FLOAT_TYPE) { typeToCheck = aExprTypeHelper.righExprType; aFloatType = aExprTypeHelper.leftExprType; } else { typeToCheck = aExprTypeHelper.leftExprType; aFloatType = aExprTypeHelper.righExprType; } if (typeToCheck.type == ExpressionType.FLOAT_TYPE || typeToCheck.type == DECIMAL_TYPE || typeToCheck.type == ExpressionType.NULL_TYPE) { exprTypeToReturn = MergeNumericTypes(typeToCheck, aFloatType); } else if (typeToCheck.type == ExpressionType.DATE_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("The Operation is invlaid"); } else if (typeToCheck.type == ExpressionType.TIMESTAMP_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("The Operation is invlaid"); } return exprTypeToReturn; } // Handle Float Ends // Handle Real Values /** * * @param aExprTypeHelper * @return ExpressionType - The expression Type is a valid expression type * which is a result of combining the two expressions */ private ExpressionType HandleReal(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; ExpressionType typeToCheck = null; ExpressionType aRealType = null; if (leftType == ExpressionType.REAL_TYPE) { typeToCheck = aExprTypeHelper.righExprType; aRealType = aExprTypeHelper.leftExprType; } else { typeToCheck = aExprTypeHelper.leftExprType; aRealType = aExprTypeHelper.righExprType; } if (typeToCheck.type == ExpressionType.REAL_TYPE || typeToCheck.type == FLOAT_TYPE || typeToCheck.type == DECIMAL_TYPE || typeToCheck.type == ExpressionType.NULL_TYPE) { exprTypeToReturn = MergeNumericTypes(typeToCheck, aRealType); } else if (typeToCheck.type == ExpressionType.DATE_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Operation is invalid"); } else if (typeToCheck.type == ExpressionType.TIMESTAMP_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("Operation is invalid"); } return exprTypeToReturn; } // Handle Real Ends // Handle Numeric /** * * @param aExprTypeHelper * @return ExpressionType - The expression Type is a valid expression type * which is a result of combining the two expressions */ private ExpressionType HandleNumeric(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; ExpressionType typeToCheck = null; ExpressionType aNumericType = null; if (leftType == ExpressionType.NUMERIC_TYPE) { typeToCheck = aExprTypeHelper.righExprType; aNumericType = aExprTypeHelper.leftExprType; } else { typeToCheck = aExprTypeHelper.leftExprType; aNumericType = aExprTypeHelper.righExprType; } if (typeToCheck.type == ExpressionType.NUMERIC_TYPE || typeToCheck.type == ExpressionType.REAL_TYPE || typeToCheck.type == ExpressionType.FLOAT_TYPE || typeToCheck.type == ExpressionType.DECIMAL_TYPE || typeToCheck.type == ExpressionType.NULL_TYPE) { exprTypeToReturn = MergeNumericTypes(typeToCheck, aNumericType); } else if (typeToCheck.type == ExpressionType.DATE_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("The Types are not compatible for // this operation"); } else if (typeToCheck.type == ExpressionType.TIMESTAMP_TYPE) { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); // throw new XDBSemanticException("The Types are not compatible for // this operation"); } return exprTypeToReturn; } // Handle Numeric ends /** * This function is responsible for merging interaction between two numeric * expressiontype * * @param expra * @param exprb * @return ExpressionType - The expression Type is a valid expression type * which is a result of combining the two expressions */ public static ExpressionType MergeNumericTypes(ExpressionType expra, ExpressionType exprb) { /* * + Precedence Matrix ForNULL SmallInt Serial Int Float Real Numeric * Decimal DoublePrecision * ------------------------------------------------------------------- 7 * 6 5 4 3 3 2 2 1 * * The algorithm is as follows : 1. Find the precedence of the type 2. * Choose the one which is the highest 3. Calculate the * length,precision,scale and type of the new type. * * ..REAL and FLOAT have lengths ..INT ,SMALLINT , SERIAL ,DOUBLE * PRECISION have none .. NUMERIC , DECIMAL have precision and scale * * If the Precision goes higher than 38 we return a float */ int length = -1; int precision = -1; int scale = -1; int type = 0; int exprap = expra.getTypePrecedence(); int exprbp = exprb.getTypePrecedence(); type = exprbp < exprap ? exprb.type : expra.type; ExpressionType exprType = new ExpressionType(); // Incase we have a case of double precision - there is no need to do // any analysis // Just return the double precision value if (type == ExpressionType.DOUBLEPRECISION_TYPE) { exprType.setExpressionType(type, 38, 0, 0); return exprType; } // Now we know what we are converting to what and from what // The "determinePrecisionValues()" function change the length for float // and real into precision and scale. expra.determinePrecisionValues(expra); exprb.determinePrecisionValues(exprb); int precision1 = expra.precision; int scale1 = expra.scale; int precision2 = exprb.precision; int scale2 = exprb.scale; precision = precision1 + precision2; scale = scale1 + scale2; // For eg ( 20 , 10 ) ( 30, 20) - ( 50, 40) -- ( 38, 20) // but by this we will lose the most significant digits - if (precision > 38) { // Just return float precision = 0; scale = 0; length = 38; type = ExpressionType.FLOAT_TYPE; } else if (precision < 38) { // This is the normal case - let us stay as we are } length = precision; exprType.setExpressionType(type, length, precision, scale); return exprType; } /** * This function determines the precision value of the type if it is * converted to another * * @param toConvert */ void determinePrecisionValues(ExpressionType toConvert) { if (toConvert.type == ExpressionType.INT_TYPE) { toConvert.length = 10; toConvert.precision = 10; toConvert.scale = 0; } else if (toConvert.type == ExpressionType.SMALLINT_TYPE) { toConvert.length = 5; toConvert.precision = 5; toConvert.scale = 0; } else if (toConvert.type == ExpressionType.BIGINT_TYPE) { toConvert.length = 16; toConvert.precision = 16; toConvert.scale = 0; } else if (toConvert.type == ExpressionType.FLOAT_TYPE || toConvert.type == ExpressionType.REAL_TYPE) { if (toConvert.length == 0) { toConvert.length = 16; toConvert.precision = 16; toConvert.scale = 0; } else { toConvert.precision = length; scale = 0; } } else if (toConvert.type == NUMERIC_TYPE || toConvert.type == DECIMAL_TYPE) { length = toConvert.length; if (toConvert.precision == -1) { precision = 0; } else { precision = toConvert.precision; } if (toConvert.scale == -1) { scale = 0; } else { scale = toConvert.scale; } } else if (toConvert.type == DOUBLEPRECISION_TYPE) { length = 38; precision = 38; scale = 0; } } /** * Handles INT interaction with other data types * * @param aExprTypeHelper * @return ExpressionType - The expression Type is a valid expression type * which is a result of combining the two expressions */ private ExpressionType HandleInt(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; ExpressionType typeToCheck = null; ExpressionType aIntType = null; String Operator = aExprTypeHelper.Operator; if (Operator.equals(">") == true || Operator.equals(">=") == true || Operator.equals("<") == true || Operator.equals("<=") == true || Operator.equals("!=") == true || Operator.equals("<>") == true) { // return BOOLEAN exprTypeToReturn.setExpressionType(ExpressionType.BOOLEAN_TYPE, -1, -1, -1); return exprTypeToReturn; } if (leftType == ExpressionType.INT_TYPE) { typeToCheck = aExprTypeHelper.righExprType; aIntType = aExprTypeHelper.leftExprType; } else { typeToCheck = aExprTypeHelper.leftExprType; aIntType = aExprTypeHelper.righExprType; } if (typeToCheck.type == ExpressionType.INT_TYPE || typeToCheck.type == ExpressionType.SMALLINT_TYPE || typeToCheck.type == ExpressionType.BIGINT_TYPE || typeToCheck.type == ExpressionType.NULL_TYPE) { exprTypeToReturn.setExpressionType(ExpressionType.FLOAT_TYPE, 32, 0, 0); } else if (typeToCheck.type == ExpressionType.NUMERIC_TYPE || typeToCheck.type == ExpressionType.REAL_TYPE || typeToCheck.type == ExpressionType.FLOAT_TYPE || typeToCheck.type == ExpressionType.DECIMAL_TYPE) { exprTypeToReturn = MergeNumericTypes(typeToCheck, aIntType); } else if (typeToCheck.type == ExpressionType.DATE_TYPE) { exprTypeToReturn.setExpressionType(DATE_TYPE, ExpressionType.DATELEN, -1, -1); } else if (typeToCheck.type == ExpressionType.TIMESTAMP_TYPE) { exprTypeToReturn.setExpressionType(TIMESTAMP_TYPE, ExpressionType.TIMESTAMPLEN, -1, -1); } return exprTypeToReturn; } /** * Handles BIGINT interaction with other data types * * @param aExprTypeHelper * @return ExpressionType - The expression Type is a valid expression type * which is a result of combining the two expressions */ private ExpressionType HandleBigInt(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; ExpressionType typeToCheck = null; ExpressionType aIntType = null; if (leftType == ExpressionType.BIGINT_TYPE) { typeToCheck = aExprTypeHelper.righExprType; aIntType = aExprTypeHelper.leftExprType; } else { typeToCheck = aExprTypeHelper.leftExprType; aIntType = aExprTypeHelper.righExprType; } if (typeToCheck.type == ExpressionType.INT_TYPE || typeToCheck.type == ExpressionType.SMALLINT_TYPE || typeToCheck.type == ExpressionType.BIGINT_TYPE || typeToCheck.type == ExpressionType.NULL_TYPE) { exprTypeToReturn.setExpressionType(ExpressionType.FLOAT_TYPE, 32, 0, 0); } else if (typeToCheck.type == ExpressionType.NUMERIC_TYPE || typeToCheck.type == ExpressionType.REAL_TYPE || typeToCheck.type == ExpressionType.FLOAT_TYPE || typeToCheck.type == ExpressionType.DECIMAL_TYPE) { exprTypeToReturn = MergeNumericTypes(typeToCheck, aIntType); } else if (typeToCheck.type == ExpressionType.DATE_TYPE) { exprTypeToReturn.setExpressionType(DATE_TYPE, ExpressionType.DATELEN, -1, -1); } else if (typeToCheck.type == ExpressionType.TIMESTAMP_TYPE) { exprTypeToReturn.setExpressionType(TIMESTAMP_TYPE, ExpressionType.TIMESTAMPLEN, -1, -1); } return exprTypeToReturn; } /** * Handles Small Int's interaction with other data type * * @param aExprTypeHelper * @return ExpressionType - The expression Type is a valid expression type * which is a result of combining the two expressions */ private ExpressionType HandleSmallInt(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; // The value returned by these function should depened on the operator // used. // For eg. If the operator is + , -, * // or if the operator is divide ExpressionType typeToCheck = null; ExpressionType aSmallIntType = null; if (leftType == ExpressionType.SMALLINT_TYPE) { typeToCheck = aExprTypeHelper.righExprType; aSmallIntType = aExprTypeHelper.leftExprType; } else { typeToCheck = aExprTypeHelper.leftExprType; aSmallIntType = aExprTypeHelper.righExprType; } if (typeToCheck.type == ExpressionType.NUMERIC_TYPE || typeToCheck.type == ExpressionType.REAL_TYPE || typeToCheck.type == ExpressionType.FLOAT_TYPE || typeToCheck.type == ExpressionType.DECIMAL_TYPE || typeToCheck.type == ExpressionType.INT_TYPE || typeToCheck.type == ExpressionType.BIGINT_TYPE || typeToCheck.type == ExpressionType.NULL_TYPE) { exprTypeToReturn = MergeNumericTypes(typeToCheck, aSmallIntType); } else if (typeToCheck.type == ExpressionType.DATE_TYPE) { exprTypeToReturn.setExpressionType(DATE_TYPE, ExpressionType.DATELEN, -1, -1); } else if (typeToCheck.type == ExpressionType.TIMESTAMP_TYPE) { exprTypeToReturn.setExpressionType(TIMESTAMP_TYPE, ExpressionType.TIMESTAMPLEN, -1, -1); } return exprTypeToReturn; } /** * Handles Double Precision * * @param aExprTypeHelper * @return ExpressionType - The expression Type is a valid expression type * which is a result of combining the two expressions */ private ExpressionType HandleDoublePrecison(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; ExpressionType typeToCheck = null; ExpressionType aDoublePrecisionType = null; if (leftType == ExpressionType.DOUBLEPRECISION_TYPE) { typeToCheck = aExprTypeHelper.righExprType; aDoublePrecisionType = aExprTypeHelper.leftExprType; } else { typeToCheck = aExprTypeHelper.leftExprType; aDoublePrecisionType = aExprTypeHelper.righExprType; } if (typeToCheck.type == ExpressionType.DOUBLEPRECISION_TYPE || typeToCheck.type == ExpressionType.INT_TYPE || typeToCheck.type == ExpressionType.BIGINT_TYPE || typeToCheck.type == ExpressionType.NUMERIC_TYPE || typeToCheck.type == ExpressionType.REAL_TYPE || typeToCheck.type == ExpressionType.SMALLINT_TYPE || typeToCheck.type == ExpressionType.FLOAT_TYPE || typeToCheck.type == DECIMAL_TYPE || typeToCheck.type == ExpressionType.NULL_TYPE) { if (aExprTypeHelper.Operator == "~") { exprTypeToReturn.setExpressionType(ExpressionType.BOOLEAN_TYPE, -1, -1, -1); } else { exprTypeToReturn = MergeNumericTypes(typeToCheck, aDoublePrecisionType); } } else if (typeToCheck.type == ExpressionType.DATE_TYPE) { exprTypeToReturn.setExpressionType(DATE_TYPE, ExpressionType.DATELEN, -1, -1); } else if (typeToCheck.type == ExpressionType.TIMESTAMP_TYPE) { exprTypeToReturn.setExpressionType(TIMESTAMP_TYPE, ExpressionType.TIMESTAMPLEN, -1, -1); } else if (typeToCheck.type == ExpressionType.CHAR_TYPE || typeToCheck.type == ExpressionType.VARCHAR_TYPE) { exprTypeToReturn.setExpressionType(typeToCheck.type, typeToCheck.length + aDoublePrecisionType.length, -1, -1); } if (exprTypeToReturn.type == 0) { exprTypeToReturn.setExpressionType( ExpressionType.DOUBLEPRECISION_TYPE, -1, -1, -1); } return exprTypeToReturn; } /** * Handles CLOB type * * @param aExprTypeHelper * @return ExpressionType - The expression Type is a valid expression type * which is a result of combining the two expressions */ private ExpressionType HandleClobType(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); exprTypeToReturn.setExpressionType(ExpressionType.CLOB_TYPE, 0, 0, 0); return exprTypeToReturn; } /** * Handles Time Type * * @param aExprTypeHelper * @return ExpressionType - The expression Type is a valid expression type * which is a result of combining the two expressions */ private ExpressionType HandleTimeType(ExprTypeHelper aExprTypeHelper) { ExpressionType exprTypeToReturn = new ExpressionType(); int leftType = aExprTypeHelper.leftExprType.type; ExpressionType typeToCheck = null; ExpressionType aTimeType = null; if (leftType == ExpressionType.TIME_TYPE) { typeToCheck = aExprTypeHelper.righExprType; aTimeType = aExprTypeHelper.leftExprType; } else { typeToCheck = aExprTypeHelper.leftExprType; aTimeType = aExprTypeHelper.righExprType; } if (typeToCheck.type == ExpressionType.NULL_TYPE || typeToCheck.type == ExpressionType.DATE_TYPE) { exprTypeToReturn = aTimeType; return exprTypeToReturn; } else { throw new InvalidExpressionException(aExprTypeHelper.leftExprType, aExprTypeHelper.Operator, aExprTypeHelper.righExprType); } // throw new XDBSemanticException("Operation not allowed for this // particular data type"); } /** * Determine data type returned by operator if possible * * @param operator * @return */ private ExpressionType HandleOperator(String operator) { ExpressionType eType = null; if ("=".equals(operator) || "!=".equals(operator) || "<=".equals(operator) || ">=".equals(operator) || "<".equals(operator) || ">".equals(operator) || "<>".equals(operator) || "is".equals(operator) || "is not".equals(operator)) { eType = new ExpressionType(); eType.setExpressionType(BOOLEAN_TYPE, 0, 0, 0); return eType; } return null; } // For SmallInt Serial Int Float Real Numeric Decimal DoublePrecision // ------------------------------------------------------------------- // 6 5 4 3 3 2 2 1 /** * Each numeric data type is given a precedence and if two numeric types are * joined with a numeric type of another data type, The one with a higher * value is converted to the lower value. * * This function just checks the type of the expression and returns * appropriate value. * * @return a integer which is the precedence value */ public int getTypePrecedence() { int precedenceNumber = 0; switch (type) { case SMALLINT_TYPE: precedenceNumber = 6; break; case INT_TYPE: precedenceNumber = 5; break; case BIGINT_TYPE: precedenceNumber = 4; break; case REAL_TYPE: precedenceNumber = 3; break; case FLOAT_TYPE: precedenceNumber = 3; break; case NUMERIC_TYPE: precedenceNumber = 2; break; case DECIMAL_TYPE: precedenceNumber = 2; break; case DOUBLEPRECISION_TYPE: precedenceNumber = 1; break; case NULL_TYPE: precedenceNumber = 7; break; } return precedenceNumber; } /** * Returns the byte length of the column. Note this may vary slightly from * vendor to vendor */ public int getByteLength() { int byteLength; switch (this.type) { case java.sql.Types.BIT: byteLength = 1; break; case java.sql.Types.BINARY: byteLength = this.length; break; case java.sql.Types.VARBINARY: byteLength = this.length; break; case java.sql.Types.CHAR: byteLength = this.length; break; case java.sql.Types.VARCHAR: case ExpressionType.REGCLASS_TYPE: byteLength = this.length / 3; break; case java.sql.Types.SMALLINT: byteLength = 2; break; case java.sql.Types.INTEGER: byteLength = 4; break; case java.sql.Types.BIGINT: byteLength = 8; break; case java.sql.Types.DECIMAL: byteLength = 4; // should be ok? break; case java.sql.Types.NUMERIC: byteLength = 4; // should be ok? break; case java.sql.Types.REAL: byteLength = 8; break; case java.sql.Types.FLOAT: byteLength = 8; break; case java.sql.Types.DATE: byteLength = 2; break; case java.sql.Types.TIME: byteLength = 2; break; case java.sql.Types.TIMESTAMP: byteLength = 4; break; case java.sql.Types.DOUBLE: byteLength = 8; break; case java.sql.Types.BOOLEAN: byteLength = 1; break; case java.sql.Types.CLOB: byteLength = 1; break; case java.sql.Types.BLOB: byteLength = 1; break; case ExpressionType.MACADDR_TYPE: byteLength = 19; break; case ExpressionType.CIDR_TYPE: byteLength = 19; break; case ExpressionType.INET_TYPE: byteLength = 19; break; case ExpressionType.GEOMETRY_TYPE: case ExpressionType.BOX2D_TYPE: case ExpressionType.BOX3D_TYPE: case ExpressionType.BOX3DEXTENT_TYPE: byteLength = this.length; break; case ExpressionType.INTERVAL_TYPE: byteLength = 12; break; default: throw new XDBServerException( ErrorMessageRepository.INVALID_DATATYPE + "(" + type + " )", 0, ErrorMessageRepository.INVALID_DATATYPE_CODE); } return byteLength; } }